Explore salinity adaptation

Suggested adaptive loci to low salinity (Baltic Sea) from Han et al. (2020)

source("../Rscripts/BaseScripts.R")

sa<-read.csv("../Data/han_SI_salinity_snp.csv")
table(sa$CHR)
# 1   2   4   6   7   8   9  10  12  13  16  17  18  22  24  26 
#50 162 189   5  14   5  23 312 411  33 129 557 388  14   5   6 

# chr1, 2, 4, 10,12, 16,17,18 have many loci

saS<-sa[,c("CHR","POS","log10P.Spring..raw.")]

ggplot()+
    geom_point(data=sa,aes(x=POS, y=log10P.Spring..raw.,color="gray50"), size=.6)+
    geom_point(data=sa,aes(x=POS, y=log10P.Autumn..raw.,color="steelblue",),color="steelblue", size=0.6)+
    facet_wrap(~CHR)+xlab('')+
    scale_colour_manual(values=c(Spring_spawner="gray50", Autumn_spawner="steelblue"))+
    theme_bw()+ylab("Log10(P)")+
    theme(legend.title = element_blank())
ggsave("../Output/Salinity/Han_Salinity_adaptiveLoci_inAtlanticHerring.png", width = 8, height = 6, dpi=300)

Fst contrast between CA and other regions

#pull out the Fst info for CA vs. other populations
fst17<-read.csv("../Output/SFS/Fst_window_year2017_combined.csv", row.names = 1)

ca<-fst17[,c(1:3,grep("CA", colnames(fst17)))]

ca$ch<-as.integer(gsub("chr","",ca$chr))
ca<-ca[order(ca$ch, ca$midPos),]

ca$chr<-factor(ca$chr, levels=paste0("chr",1:26))

plots<-list()
for (i in 1:5){
    fs<-gsub("Fst_","",colnames(ca)[i+3])
    pops <- unlist(strsplit(fs, "\\."))
    plots[[i]] <- ggplot(ca, aes_string(x = 'midPos', y = paste0(colnames(ca)[i+3]))) + 
        geom_point(size = 1, color = "gray",alpha = 0.4, shape = 1)+
        theme_minimal()+
        theme(axis.text.x=element_blank())+
        ylab("Fst\n")+ xlab("")+ ylim(0,0.85)+
        ggtitle(paste0(pops[1]," vs.", pops[2]))+
        geom_line(color="steelblue", size=0.2)+
        facet_wrap(~chr, ncol = 9)
}

{png(paste0("../Output/SFS/CA_Fst.png"), height = 20, width = 20, res=150, units = "in")
do.call(grid.arrange, c(plots, ncol=2))
dev.off()}

Select the chromosome of interests only

  • chr1,2,4,6,7,8,9,10,12,13,16,17,18,22,24,26

Look at AF from VCF files in CA17

#run vcftools to get AF info
#(getAF_eachPop.sh)
vcftools --gzvcf /home/ktist/ph/data/new_vcf/MD7000/population/CA17_maf05.vcf.gz --freq --out  /home/ktist/ph/data/new_vcf/MD7000/population/AF/CA17_maf05_af 

Plot the freq near adaptive loci

  • SNPs within the identified salinity adaptive loci +-25000 bases
  • Plot the MAFs (Minior allele freq.)
af<-read.table("../Data/new_vcf/AF/CA17_maf05_af.frq",skip=1, col.names = c("chr","pos","n_allele","n_sample","MajorAF","MAF"))

af$maf<-as.numeric(substr(af$MAF, 3,10))
af$maj<-as.numeric(substr(af$MajorAF, 3,10))

chromosomes<-unique(sa$CHR)
saloci<-data.frame()
for (i in 1:length(chromosomes)){
    snp<-sa[sa$CHR==chromosomes[i],]
    snp$range1<-snp$POS-25000
    snp$range2<-snp$POS+25000
    #range vector
    range<-c()
    for(j in 1:nrow(snp)){
         range<-c(range, seq(snp$range1[j], snp$range2[j], by=1))
    }

    af2<-af[af$chr==paste0("chr",chromosomes[i]),]
    ovlp<-af2[af2$pos %in% range, ]
    saloci<-rbind(saloci, ovlp)
}
write.csv(saloci, "../Output/Salinity/Salinity_adaptive_snps_CA17.csv")
#saloci<-read.csv("../Output/Salinity/Salinity_adaptive_snps_CA17.csv", row.names = 1)

# look at MAF of loci near the adaptive snps identified as salinity tolerant
saloci$chr<-factor(saloci$chr, levels=paste0("chr", chromosomes))
ggplot(saloci, aes(x=pos,y=maf))+
    geom_point(size=0.5, color="blue", alpha=0.5)+
    facet_wrap(~chr)+
    theme_bw()+ggtitle("CA")
ggsave("../Output/Salinity/CA_salinity_adaptiveLoci.png", width = 8, height = 5.5, dpi=300)

Look at the frequencies in all other 2017 populations

#Look at the freq for all other 2017 populations
pops<-c("PWS17","SS17","TB17","BC17","WA17")

for (p in 1:length(pops)){
    af1<-read.table(paste0("../Data/new_vcf/AF/",pops[p], "_maf05_af.frq"),skip=1, col.names=c("chr","pos","n_allele","n_sample","MajorAF","MAF"))
    af1$maf<-as.numeric(substr(af1$MAF, 3,10))
    af1$maj<-as.numeric(substr(af1$MajorAF, 3,10))
    
    df<-data.frame()
    for (i in 1:length(chromosomes)){
        loci<-saloci$pos[saloci$chr==paste0("chr", chromosomes[i])]
        ovlp<-af1[af1$chr==paste0("chr",chromosomes[i]) & af1$pos %in% loci,]
        df<-rbind(df, ovlp)
    }
    
    assign(paste0(pops[p]) ,df)
    #write.csv(df, paste0("../Output/Salinity/Salinity_adaptive_snps_", pops[p],".csv"))
}

#Plot different populations    
PWS17$chr<-factor(PWS17$chr, levels=paste0("chr", chromosomes))
ggplot(PWS17, aes(x=pos,y=maf))+
    geom_point(size=0.5, color="blue", alpha=0.5)+
    facet_wrap(~chr)+
    theme_bw()+ggtitle("PWS")
ggsave("../Output/PWS17_salinity_adaptiveLoci.png", width = 8, height = 5.5, dpi=300)

#Plot different populations    
WA17$chr<-factor(WA17$chr, levels=paste0("chr", chromosomes))
ggplot(WA17, aes(x=pos,y=maf))+
    geom_point(size=0.5, color="blue", alpha=0.5)+
    facet_wrap(~chr)+
    theme_bw()+ggtitle("WA")
ggsave("../Output/WA17_salinity_adaptiveLoci.png", width = 10, height = 7, dpi=300)

* All look similar

Run Chi-square test bewteen populations to test if AF differ

Are alternate frequencies higher (maf) in ‘Salinity Adaptive SNPs’ in CA, compared to other populations?

af$color<-"A"
af$color[af$maf>0.5]<-"B"

ggplot(af, aes(x=pos,y=maf, color=color))+
    geom_point(size=0.2)+
    scale_color_manual(values=c("gray75", "blue"))+
    facet_wrap(~chr)+
    theme_bw()+ggtitle("CA")
ggsave("../Output/Salinity/CA_MAF_plot_all_chromosomes.png", width = 8, height = 8, dpi=300)

# Proportion of maf over 0.5 (alternate higher than reference) in CA pop
nrow(af[af$maf>0.5,]) # 19264
nrow(af[af$maf>0.5,])/nrow(af) #0.05829062 
#salinity adaptive loci
nrow(saloci[saloci$maf>0.5,])/nrow(saloci) #0.1474945 much higher


#sites without the salinity-adaptive loci (the ratio does not change much from all sites above)
saloci$id<-paste0(saloci$chr,".",saloci$pos)
af$id<-paste0(af$chr,".",af$pos)
af2<-af[!(af$id %in% saloci$id),]
nrow(af2[af2$maf>0.5,])/nrow(af2) #0.05742586

## Compare with other population
nrow(PWS17[PWS17$maf>0.5,])/nrow(PWS17) #0.03277655
prop<-data.frame(pop=pops)
for (i in 1:length(pops)){
    df<-get(pops[i])
    prop$maf_over0.5_prop[i]<-nrow(df[df$maf>0.5,])/nrow(df)
}
prop<-rbind(prop, c("CA17", nrow(saloci[saloci$maf>0.5,])/nrow(saloci)))
prop$maf_over0.5_prop<-as.numeric(prop$maf_over0.5_prop)
prop
#    pop maf_over0.5_prop
#1 PWS17       0.03277655
#2  SS17       0.03561298
#3  TB17       0.03057044
#4  BC17       0.04034037
#5  WA17       0.03592814
#6  CA17       0.14749448


ggplot(prop, aes(x=pop, y=maf_over0.5_prop))+
    geom_bar(stat="identity")+ylab("Proportion of MAF > 0.5 in Salinity Adaptive Loci")
ggsave("../Output/Salinity/Proportion.MAF.over0.5.in.Salinity.Adaptive.Loci.png", width = 5, height = 4, dpi=300)

  • CA has a higher proportion of salinity adaptive loci with allele freq. >0.5
  • Is this due to inversion in chr12?
  • Remove loci within Chr12 inversion
af$color<-"A"

#Is it due to inversion?
#remove the inversion region? (remove chr12)
prop2<-data.frame(pop=pops)
for (i in 1:length(pops)){
    df<-get(pops[i])
    df<-df[df$chr!="chr12",]
    prop2$maf_over0.5_prop[i]<-nrow(df[df$maf>0.5,])/nrow(df)
}
prop2<-rbind(prop2, c("CA17", nrow(saloci[saloci$maf>0.5&saloci$chr!="chr12",])/nrow(saloci[saloci$chr!="chr12",])))
prop2$maf_over0.5_prop<-as.numeric(prop2$maf_over0.5_prop)
prop2
#    pop maf_over0.5_prop
#1 PWS17       0.03789224
#2  SS17       0.04026051
#3  TB17       0.03907638
#4  BC17       0.04440497
#5  WA17       0.03907638
#6  CA17       0.04677324
#the difference disappers by removing chr12 (inversion)

ggplot(prop2, aes(x=pop, y=maf_over0.5_prop))+
    geom_bar(stat="identity")+ylab("Proportion of MAF > 0.5 (no Chr12 Inv)")
ggsave("../Output/Salinity/Proportion.MAF.over0.5.in.Salinity.Adaptive.Loci_withoutChr12Inv.png", width = 5, height = 4, dpi=300)

look at chr1, chr4, chr10, and chr16 separately

pops2<-c(pops,"CA17")
CA17<-saloci

prop3<-data.frame(pop=pops2)
for (i in 1:length(pops2)){
    df<-get(pops2[i])
    df1<-df[df$chr=="chr1",]
    prop3$chr1[i]<-nrow(df1[df1$maf>0.5,])/nrow(df1)
    df1<-df[df$chr=="chr4",]
    prop3$chr4[i]<-nrow(df1[df1$maf>0.5,])/nrow(df1)
    df1<-df[df$chr=="chr10",]
    prop3$chr10[i]<-nrow(df1[df1$maf>0.5,])/nrow(df1)
    df1<-df[df$chr=="chr16",]
    prop3$chr16[i]<-nrow(df1[df1$maf>0.5,])/nrow(df1)
}

prop3m<-melt(prop3, id.vars="pop")
ggplot(prop3m, aes(x=variable, y=value, color=pop))+
    geom_point(position=position_dodge(width = 0.5), size=3)+
    geom_vline(xintercept = c(1.5,2.5,3.5), color="gray",size=0.5)+
    theme_bw()+ylab("Proportion of AF >0.5")+xlab("")+theme(legend.title = element_blank())+
    theme(panel.grid.major.x = element_blank())
ggsave("../Output/Salinity/PropAFover0.5.in.allPops.ch4.10.16.png", width=7, height=4, dpi=300 )    

LS0tCnRpdGxlOiAiU2FsaW5pdHkgQWRhcHRhdGlvbiIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICAgIHRvYzogdHJ1ZSAKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgICAgdGhlbWU6IGx1bWVuCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICAgIGRmX3ByaW50OiBwYWdlZApkYXRlOiAiMDcvMDUvMjAyMiIKCi0tLQoKIyMgRXhwbG9yZSBzYWxpbml0eSBhZGFwdGF0aW9uICAKCiMjIyBTdWdnZXN0ZWQgYWRhcHRpdmUgbG9jaSB0byBsb3cgc2FsaW5pdHkgKEJhbHRpYyBTZWEpIGZyb20gSGFuIGV0IGFsLiAoMjAyMCkKCmBgYHtyIGV2YWw9RkFMU0UsIGV2YWw9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNvdXJjZSgiLi4vUnNjcmlwdHMvQmFzZVNjcmlwdHMuUiIpCgpzYTwtcmVhZC5jc3YoIi4uL0RhdGEvaGFuX1NJX3NhbGluaXR5X3NucC5jc3YiKQp0YWJsZShzYSRDSFIpCiMgMSAgIDIgICA0ICAgNiAgIDcgICA4ICAgOSAgMTAgIDEyICAxMyAgMTYgIDE3ICAxOCAgMjIgIDI0ICAyNiAKIzUwIDE2MiAxODkgICA1ICAxNCAgIDUgIDIzIDMxMiA0MTEgIDMzIDEyOSA1NTcgMzg4ICAxNCAgIDUgICA2IAoKIyBjaHIxLCAyLCA0LCAxMCwxMiwgMTYsMTcsMTggaGF2ZSBtYW55IGxvY2kKCnNhUzwtc2FbLGMoIkNIUiIsIlBPUyIsImxvZzEwUC5TcHJpbmcuLnJhdy4iKV0KCmdncGxvdCgpKwogICAgZ2VvbV9wb2ludChkYXRhPXNhLGFlcyh4PVBPUywgeT1sb2cxMFAuU3ByaW5nLi5yYXcuLGNvbG9yPSJncmF5NTAiKSwgc2l6ZT0uNikrCiAgICBnZW9tX3BvaW50KGRhdGE9c2EsYWVzKHg9UE9TLCB5PWxvZzEwUC5BdXR1bW4uLnJhdy4sY29sb3I9InN0ZWVsYmx1ZSIsKSxjb2xvcj0ic3RlZWxibHVlIiwgc2l6ZT0wLjYpKwogICAgZmFjZXRfd3JhcCh+Q0hSKSt4bGFiKCcnKSsKICAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzPWMoU3ByaW5nX3NwYXduZXI9ImdyYXk1MCIsIEF1dHVtbl9zcGF3bmVyPSJzdGVlbGJsdWUiKSkrCiAgICB0aGVtZV9idygpK3lsYWIoIkxvZzEwKFApIikrCiAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCmdnc2F2ZSgiLi4vT3V0cHV0L1NhbGluaXR5L0hhbl9TYWxpbml0eV9hZGFwdGl2ZUxvY2lfaW5BdGxhbnRpY0hlcnJpbmcucG5nIiwgd2lkdGggPSA4LCBoZWlnaHQgPSA2LCBkcGk9MzAwKQoKYGBgCiFbXSguLi9PdXRwdXQvU2FsaW5pdHkvSGFuX1NhbGluaXR5X2FkYXB0aXZlTG9jaV9pbkF0bGFudGljSGVycmluZy5wbmcpICAKCiMjIyBGc3QgY29udHJhc3QgYmV0d2VlbiBDQSBhbmQgb3RoZXIgcmVnaW9ucyAKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI3B1bGwgb3V0IHRoZSBGc3QgaW5mbyBmb3IgQ0EgdnMuIG90aGVyIHBvcHVsYXRpb25zCmZzdDE3PC1yZWFkLmNzdigiLi4vT3V0cHV0L1NGUy9Gc3Rfd2luZG93X3llYXIyMDE3X2NvbWJpbmVkLmNzdiIsIHJvdy5uYW1lcyA9IDEpCgpjYTwtZnN0MTdbLGMoMTozLGdyZXAoIkNBIiwgY29sbmFtZXMoZnN0MTcpKSldCgpjYSRjaDwtYXMuaW50ZWdlcihnc3ViKCJjaHIiLCIiLGNhJGNocikpCmNhPC1jYVtvcmRlcihjYSRjaCwgY2EkbWlkUG9zKSxdCgpjYSRjaHI8LWZhY3RvcihjYSRjaHIsIGxldmVscz1wYXN0ZTAoImNociIsMToyNikpCgpwbG90czwtbGlzdCgpCmZvciAoaSBpbiAxOjUpewogICAgZnM8LWdzdWIoIkZzdF8iLCIiLGNvbG5hbWVzKGNhKVtpKzNdKQogICAgcG9wcyA8LSB1bmxpc3Qoc3Ryc3BsaXQoZnMsICJcXC4iKSkKICAgIHBsb3RzW1tpXV0gPC0gZ2dwbG90KGNhLCBhZXNfc3RyaW5nKHggPSAnbWlkUG9zJywgeSA9IHBhc3RlMChjb2xuYW1lcyhjYSlbaSszXSkpKSArIAogICAgICAgIGdlb21fcG9pbnQoc2l6ZSA9IDEsIGNvbG9yID0gImdyYXkiLGFscGhhID0gMC40LCBzaGFwZSA9IDEpKwogICAgICAgIHRoZW1lX21pbmltYWwoKSsKICAgICAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCkpKwogICAgICAgIHlsYWIoIkZzdFxuIikrIHhsYWIoIiIpKyB5bGltKDAsMC44NSkrCiAgICAgICAgZ2d0aXRsZShwYXN0ZTAocG9wc1sxXSwiIHZzLiIsIHBvcHNbMl0pKSsKICAgICAgICBnZW9tX2xpbmUoY29sb3I9InN0ZWVsYmx1ZSIsIHNpemU9MC4yKSsKICAgICAgICBmYWNldF93cmFwKH5jaHIsIG5jb2wgPSA5KQp9Cgp7cG5nKHBhc3RlMCgiLi4vT3V0cHV0L1NGUy9DQV9Gc3QucG5nIiksIGhlaWdodCA9IDIwLCB3aWR0aCA9IDIwLCByZXM9MTUwLCB1bml0cyA9ICJpbiIpCmRvLmNhbGwoZ3JpZC5hcnJhbmdlLCBjKHBsb3RzLCBuY29sPTIpKQpkZXYub2ZmKCl9CmBgYAohW10oLi4vT3V0cHV0L1NGUy9DQV9Gc3QucG5nKQoKIyMjIFNlbGVjdCB0aGUgY2hyb21vc29tZSBvZiBpbnRlcmVzdHMgb25seSAgCgoqIGNocjEsMiw0LDYsNyw4LDksMTAsMTIsMTMsMTYsMTcsMTgsMjIsMjQsMjYKCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmNhMjwtY2FbY2EkY2ggJWluJSBjKDEsMiw0LDYsNyw4LDksMTAsMTIsMTMsMTYsMTcsMTgsMjIsMjQsMjYpLF0KcGxvdHMyPC1saXN0KCkKZm9yIChpIGluIDE6NSl7IAogICAgZnM8LWdzdWIoIkZzdF8iLCIiLGNvbG5hbWVzKGNhMilbaSszXSkKICAgIHBvcHMgPC0gdW5saXN0KHN0cnNwbGl0KGZzLCAiXFwuIikpCiAgICAjIEZzdCB3aXRoIGFjdHVhbCBsaW5lIHRvIGhpZ2hsaWdodCB0aGUgZGlmZmVyZW5jZXMKICAgIHBsb3RzMltbaV1dIDwtIGdncGxvdChjYTIsIGFlc19zdHJpbmcoeCA9ICdtaWRQb3MnLCB5ID0gcGFzdGUwKGNvbG5hbWVzKGNhMilbaSszXSkpKSArIAogICAgICAgIGdlb21fcG9pbnQoc2l6ZSA9IDEsIGNvbG9yID0gImdyYXkiLGFscGhhID0gMC40LCBzaGFwZSA9IDEpKwogICAgICAgIHRoZW1lX21pbmltYWwoKSsKICAgICAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCkpKwogICAgICAgIHlsYWIoIkZzdFxuIikrIHhsYWIoIiIpKyB5bGltKDAsMC44NSkrCiAgICAgICAgZ2d0aXRsZShwYXN0ZTAocG9wc1sxXSwiIHZzLiIsIHBvcHNbMl0pKSsKICAgICAgICBnZW9tX2xpbmUoY29sb3I9InN0ZWVsYmx1ZSIsIHNpemU9MC4yKSsKICAgICAgICBmYWNldF93cmFwKH5jaHIsIG5jb2wgPTQpCn0Ke3BuZyhwYXN0ZTAoIi4uL091dHB1dC9TRlMvQ0FfRnN0X3NhbGluaXR5X2Noci5wbmciKSwgaGVpZ2h0ID0gMjAsIHdpZHRoID0gMjAsIHJlcz0zMDAsIHVuaXRzID0gImluIikKZG8uY2FsbChncmlkLmFycmFuZ2UsIGMocGxvdHMyLCBuY29sPTIpKQpkZXYub2ZmKCl9CmBgYAohW10oLi4vT3V0cHV0L1NGUy9DQV9Gc3Rfc2FsaW5pdHlfY2hyLnBuZykKCiMjIyBMb29rIGF0IEFGIGZyb20gVkNGIGZpbGVzIGluIENBMTcgCgpgYGB7YmFzaCBldmFsPUZBTFNFfQojcnVuIHZjZnRvb2xzIHRvIGdldCBBRiBpbmZvCiMoZ2V0QUZfZWFjaFBvcC5zaCkKdmNmdG9vbHMgLS1nenZjZiAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQ3MDAwL3BvcHVsYXRpb24vQ0ExN19tYWYwNS52Y2YuZ3ogLS1mcmVxIC0tb3V0ICAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQ3MDAwL3BvcHVsYXRpb24vQUYvQ0ExN19tYWYwNV9hZiAKCmBgYAoKIyMjIyBQbG90IHRoZSBmcmVxIG5lYXIgYWRhcHRpdmUgbG9jaSAKKiBTTlBzIHdpdGhpbiB0aGUgaWRlbnRpZmllZCBzYWxpbml0eSBhZGFwdGl2ZSBsb2NpICstMjUwMDAgYmFzZXMgIAoqIFBsb3QgdGhlIE1BRnMgKE1pbmlvciBhbGxlbGUgZnJlcS4pICAKCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGV2YWw9RkFMU0V9CgphZjwtcmVhZC50YWJsZSgiLi4vRGF0YS9uZXdfdmNmL0FGL0NBMTdfbWFmMDVfYWYuZnJxIixza2lwPTEsIGNvbC5uYW1lcyA9IGMoImNociIsInBvcyIsIm5fYWxsZWxlIiwibl9zYW1wbGUiLCJNYWpvckFGIiwiTUFGIikpCgphZiRtYWY8LWFzLm51bWVyaWMoc3Vic3RyKGFmJE1BRiwgMywxMCkpCmFmJG1hajwtYXMubnVtZXJpYyhzdWJzdHIoYWYkTWFqb3JBRiwgMywxMCkpCgpjaHJvbW9zb21lczwtdW5pcXVlKHNhJENIUikKc2Fsb2NpPC1kYXRhLmZyYW1lKCkKZm9yIChpIGluIDE6bGVuZ3RoKGNocm9tb3NvbWVzKSl7CiAgICBzbnA8LXNhW3NhJENIUj09Y2hyb21vc29tZXNbaV0sXQogICAgc25wJHJhbmdlMTwtc25wJFBPUy0yNTAwMAogICAgc25wJHJhbmdlMjwtc25wJFBPUysyNTAwMAogICAgI3JhbmdlIHZlY3RvcgogICAgcmFuZ2U8LWMoKQogICAgZm9yKGogaW4gMTpucm93KHNucCkpewogICAgICAgICByYW5nZTwtYyhyYW5nZSwgc2VxKHNucCRyYW5nZTFbal0sIHNucCRyYW5nZTJbal0sIGJ5PTEpKQogICAgfQoKICAgIGFmMjwtYWZbYWYkY2hyPT1wYXN0ZTAoImNociIsY2hyb21vc29tZXNbaV0pLF0KICAgIG92bHA8LWFmMlthZjIkcG9zICVpbiUgcmFuZ2UsIF0KICAgIHNhbG9jaTwtcmJpbmQoc2Fsb2NpLCBvdmxwKQp9CndyaXRlLmNzdihzYWxvY2ksICIuLi9PdXRwdXQvU2FsaW5pdHkvU2FsaW5pdHlfYWRhcHRpdmVfc25wc19DQTE3LmNzdiIpCiNzYWxvY2k8LXJlYWQuY3N2KCIuLi9PdXRwdXQvU2FsaW5pdHkvU2FsaW5pdHlfYWRhcHRpdmVfc25wc19DQTE3LmNzdiIsIHJvdy5uYW1lcyA9IDEpCgojIGxvb2sgYXQgTUFGIG9mIGxvY2kgbmVhciB0aGUgYWRhcHRpdmUgc25wcyBpZGVudGlmaWVkIGFzIHNhbGluaXR5IHRvbGVyYW50CnNhbG9jaSRjaHI8LWZhY3RvcihzYWxvY2kkY2hyLCBsZXZlbHM9cGFzdGUwKCJjaHIiLCBjaHJvbW9zb21lcykpCmdncGxvdChzYWxvY2ksIGFlcyh4PXBvcyx5PW1hZikpKwogICAgZ2VvbV9wb2ludChzaXplPTAuNSwgY29sb3I9ImJsdWUiLCBhbHBoYT0wLjUpKwogICAgZmFjZXRfd3JhcCh+Y2hyKSsKICAgIHRoZW1lX2J3KCkrZ2d0aXRsZSgiQ0EiKQpnZ3NhdmUoIi4uL091dHB1dC9TYWxpbml0eS9DQV9zYWxpbml0eV9hZGFwdGl2ZUxvY2kucG5nIiwgd2lkdGggPSA4LCBoZWlnaHQgPSA1LjUsIGRwaT0zMDApCmBgYAohW10oLi4vT3V0cHV0L1NhbGluaXR5L0NBX3NhbGluaXR5X2FkYXB0aXZlTG9jaS5wbmcpCgojIyMgTG9vayBhdCB0aGUgZnJlcXVlbmNpZXMgaW4gYWxsIG90aGVyIDIwMTcgcG9wdWxhdGlvbnMKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGV2YWw9RkFMU0V9CiNMb29rIGF0IHRoZSBmcmVxIGZvciBhbGwgb3RoZXIgMjAxNyBwb3B1bGF0aW9ucwpwb3BzPC1jKCJQV1MxNyIsIlNTMTciLCJUQjE3IiwiQkMxNyIsIldBMTciKQoKZm9yIChwIGluIDE6bGVuZ3RoKHBvcHMpKXsKICAgIGFmMTwtcmVhZC50YWJsZShwYXN0ZTAoIi4uL0RhdGEvbmV3X3ZjZi9BRi8iLHBvcHNbcF0sICJfbWFmMDVfYWYuZnJxIiksc2tpcD0xLCBjb2wubmFtZXM9YygiY2hyIiwicG9zIiwibl9hbGxlbGUiLCJuX3NhbXBsZSIsIk1ham9yQUYiLCJNQUYiKSkKICAgIGFmMSRtYWY8LWFzLm51bWVyaWMoc3Vic3RyKGFmMSRNQUYsIDMsMTApKQogICAgYWYxJG1hajwtYXMubnVtZXJpYyhzdWJzdHIoYWYxJE1ham9yQUYsIDMsMTApKQogICAgCiAgICBkZjwtZGF0YS5mcmFtZSgpCiAgICBmb3IgKGkgaW4gMTpsZW5ndGgoY2hyb21vc29tZXMpKXsKICAgICAgICBsb2NpPC1zYWxvY2kkcG9zW3NhbG9jaSRjaHI9PXBhc3RlMCgiY2hyIiwgY2hyb21vc29tZXNbaV0pXQogICAgICAgIG92bHA8LWFmMVthZjEkY2hyPT1wYXN0ZTAoImNociIsY2hyb21vc29tZXNbaV0pICYgYWYxJHBvcyAlaW4lIGxvY2ksXQogICAgICAgIGRmPC1yYmluZChkZiwgb3ZscCkKICAgIH0KICAgIAogICAgYXNzaWduKHBhc3RlMChwb3BzW3BdKSAsZGYpCiAgICAjd3JpdGUuY3N2KGRmLCBwYXN0ZTAoIi4uL091dHB1dC9TYWxpbml0eS9TYWxpbml0eV9hZGFwdGl2ZV9zbnBzXyIsIHBvcHNbcF0sIi5jc3YiKSkKfQoKI1Bsb3QgZGlmZmVyZW50IHBvcHVsYXRpb25zICAgIApQV1MxNyRjaHI8LWZhY3RvcihQV1MxNyRjaHIsIGxldmVscz1wYXN0ZTAoImNociIsIGNocm9tb3NvbWVzKSkKZ2dwbG90KFBXUzE3LCBhZXMoeD1wb3MseT1tYWYpKSsKICAgIGdlb21fcG9pbnQoc2l6ZT0wLjUsIGNvbG9yPSJibHVlIiwgYWxwaGE9MC41KSsKICAgIGZhY2V0X3dyYXAofmNocikrCiAgICB0aGVtZV9idygpK2dndGl0bGUoIlBXUyIpCmdnc2F2ZSgiLi4vT3V0cHV0L1BXUzE3X3NhbGluaXR5X2FkYXB0aXZlTG9jaS5wbmciLCB3aWR0aCA9IDgsIGhlaWdodCA9IDUuNSwgZHBpPTMwMCkKYGBgCiFbXSguLi9PdXRwdXQvUFdTMTdfc2FsaW5pdHlfYWRhcHRpdmVMb2NpLnBuZykKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXZhbD1GQUxTRX0KI1Bsb3QgZGlmZmVyZW50IHBvcHVsYXRpb25zICAgIApXQTE3JGNocjwtZmFjdG9yKFdBMTckY2hyLCBsZXZlbHM9cGFzdGUwKCJjaHIiLCBjaHJvbW9zb21lcykpCmdncGxvdChXQTE3LCBhZXMoeD1wb3MseT1tYWYpKSsKICAgIGdlb21fcG9pbnQoc2l6ZT0wLjUsIGNvbG9yPSJibHVlIiwgYWxwaGE9MC41KSsKICAgIGZhY2V0X3dyYXAofmNocikrCiAgICB0aGVtZV9idygpK2dndGl0bGUoIldBIikKZ2dzYXZlKCIuLi9PdXRwdXQvV0ExN19zYWxpbml0eV9hZGFwdGl2ZUxvY2kucG5nIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNywgZHBpPTMwMCkKYGBgCiFbXSguLi9PdXRwdXQvV0ExN19zYWxpbml0eV9hZGFwdGl2ZUxvY2kucG5nKQoqICoqQWxsIGxvb2sgc2ltaWxhcioqCgojIyMgUnVuIENoaS1zcXVhcmUgdGVzdCBiZXd0ZWVuIHBvcHVsYXRpb25zIHRvIHRlc3QgaWYgQUYgZGlmZmVyCgpgYGB7ciBldmFsPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojcnVuIGNoaSBzcXVhcmUgdGVzdCBiZXR3ZWVuIHRoZSBwb3B1bGF0aW9uCnBvcHNpemU8LWMoNTYsNjQsNzIsNjQsNzIpCkNBPC1zYWxvY2kKCmZvciAocCBpbiAxIDogbGVuZ3RoKHBvcHMpKXsKICAgIGRmPC1nZXQocG9wc1twXSkKICAgIG48LXBvcHNpemVbcF0KICAgIAogICAgY2hpLnJlc3VsdHM8LUNBWywxOjJdCiAgICBjaGkucmVzdWx0czI8LUNBWywxOjJdICNzaW11bGF0ZWQgcC12YWx1ZXMKICAgIGZvciAoaSBpbiAxOiBucm93KENBKSl7CiAgICAgICAgbWF0PC1hcy50YWJsZShyYmluZChjKHJvdW5kKENBJG1haltpXSo3MCkscm91bmQoQ0EkbWFmW2ldKjcwKSksYyhyb3VuZChkZiRtYWpbaV0qbikscm91bmQoZGYkbWFmW2ldKm4pKSkpCiAgICAgICAgZGltbmFtZXMobWF0KTwtbGlzdChwb3A9YygiQ0ExNyIsIHBvcHNbcF0pLCBhbGxlbGU9YygiUmVmIiwiQWx0IikpCgogICAgICAgIHhzcTwtY2hpc3EudGVzdChtYXQpCiAgICAgICAgY2hpLnJlc3VsdHMkcmF3UFtpXTwteHNxJHAudmFsdWUKICAgICAgICB4c3EyPC1jaGlzcS50ZXN0KG1hdCxzaW11bGF0ZS5wLnZhbHVlID0gVFJVRSwgQiA9IDIwMDApCiAgICAgICAgY2hpLnJlc3VsdHMyJHJhd1BbaV08LXhzcTIkcC52YWx1ZQogICAgfQogICAgCiAgICB3cml0ZS5jc3YoY2hpLnJlc3VsdHMsIHBhc3RlMCgiLi4vT3V0cHV0L1NhbGluaXR5L0NoaS50ZXN0X0NBLnZzIixwb3BzW3BdLCIuY3N2IikpCiAgICB3cml0ZS5jc3YoY2hpLnJlc3VsdHMyLCBwYXN0ZTAoIi4uL091dHB1dC9TYWxpbml0eS9DaGkudGVzdF9DQS52cyIscG9wc1twXSwiLnNpbVAuY3N2IikpCiAgICAKICAgIGdncGxvdChjaGkucmVzdWx0cywgYWVzKHg9cG9zLCB5PS1sb2cxMChyYXdQKSkpKwogICAgICAgIGdlb21fcG9pbnQoc2l6ZT0wLjUsIGNvbG9yPSJyZWQiLCBhbHBoYT0wLjUpK3hsYWIoJycpKwogICAgICAgIGZhY2V0X3dyYXAofmNocikrdGhlbWVfYncoKStnZ3RpdGxlKHBhc3RlMCgiQ0EgdnMuIiwgZ3N1YigiMTciLCcnLHBvcHNbcF0pKSkrCiAgICAgICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSwgY29sb3I9ImdyYXkiLCBzaXplPTAuMykKICAgIGdnc2F2ZShwYXN0ZTAoIi4uL091dHB1dC9TYWxpbml0eS9DaGkudGVzdF9DQS52cy4iLHBvcHNbcF0sIi5wbmciKSwgd2lkdGggPSA4LCBoZWlnaHQgPSA1LCBkcGkgPTIwMCkKfQpgYGAKCiFbXSguLi9PdXRwdXQvU2FsaW5pdHkvQ2hpLnRlc3RfQ0EudnMuV0ExNy5wbmcpe3dpZHRoPTQ1JX0gIVtdKC4uL091dHB1dC9TYWxpbml0eS9DaGkudGVzdF9DQS52cy5CQzE3LnBuZyl7d2lkdGg9NDUlfQoKIVtdKC4uL091dHB1dC9TYWxpbml0eS9DaGkudGVzdF9DQS52cy5TUzE3LnBuZyl7d2lkdGg9NDUlfSFbXSguLi9PdXRwdXQvU2FsaW5pdHkvQ2hpLnRlc3RfQ0EudnMuUFdTMTcucG5nKXt3aWR0aD00NSV9CgohW10oLi4vT3V0cHV0L1NhbGluaXR5L0NoaS50ZXN0X0NBLnZzLlRCMTcucG5nKXt3aWR0aD00NSV9CgoKIyMjIEFyZSBhbHRlcm5hdGUgZnJlcXVlbmNpZXMgaGlnaGVyIChtYWYpIGluICdTYWxpbml0eSBBZGFwdGl2ZSBTTlBzJyBpbiBDQSwgY29tcGFyZWQgdG8gb3RoZXIgcG9wdWxhdGlvbnM/IAoKYGBge3IgZXZhbD1GQUxTRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFfQphZiRjb2xvcjwtIkEiCmFmJGNvbG9yW2FmJG1hZj4wLjVdPC0iQiIKCmdncGxvdChhZiwgYWVzKHg9cG9zLHk9bWFmLCBjb2xvcj1jb2xvcikpKwogICAgZ2VvbV9wb2ludChzaXplPTAuMikrCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImdyYXk3NSIsICJibHVlIikpKwogICAgZmFjZXRfd3JhcCh+Y2hyKSsKICAgIHRoZW1lX2J3KCkrZ2d0aXRsZSgiQ0EiKQpnZ3NhdmUoIi4uL091dHB1dC9TYWxpbml0eS9DQV9NQUZfcGxvdF9hbGxfY2hyb21vc29tZXMucG5nIiwgd2lkdGggPSA4LCBoZWlnaHQgPSA4LCBkcGk9MzAwKQoKIyBQcm9wb3J0aW9uIG9mIG1hZiBvdmVyIDAuNSAoYWx0ZXJuYXRlIGhpZ2hlciB0aGFuIHJlZmVyZW5jZSkgaW4gQ0EgcG9wCm5yb3coYWZbYWYkbWFmPjAuNSxdKSAjIDE5MjY0Cm5yb3coYWZbYWYkbWFmPjAuNSxdKS9ucm93KGFmKSAjMC4wNTgyOTA2MiAKI3NhbGluaXR5IGFkYXB0aXZlIGxvY2kKbnJvdyhzYWxvY2lbc2Fsb2NpJG1hZj4wLjUsXSkvbnJvdyhzYWxvY2kpICMwLjE0NzQ5NDUgbXVjaCBoaWdoZXIKCgojc2l0ZXMgd2l0aG91dCB0aGUgc2FsaW5pdHktYWRhcHRpdmUgbG9jaSAodGhlIHJhdGlvIGRvZXMgbm90IGNoYW5nZSBtdWNoIGZyb20gYWxsIHNpdGVzIGFib3ZlKQpzYWxvY2kkaWQ8LXBhc3RlMChzYWxvY2kkY2hyLCIuIixzYWxvY2kkcG9zKQphZiRpZDwtcGFzdGUwKGFmJGNociwiLiIsYWYkcG9zKQphZjI8LWFmWyEoYWYkaWQgJWluJSBzYWxvY2kkaWQpLF0KbnJvdyhhZjJbYWYyJG1hZj4wLjUsXSkvbnJvdyhhZjIpICMwLjA1NzQyNTg2CgojIyBDb21wYXJlIHdpdGggb3RoZXIgcG9wdWxhdGlvbgpucm93KFBXUzE3W1BXUzE3JG1hZj4wLjUsXSkvbnJvdyhQV1MxNykgIzAuMDMyNzc2NTUKcHJvcDwtZGF0YS5mcmFtZShwb3A9cG9wcykKZm9yIChpIGluIDE6bGVuZ3RoKHBvcHMpKXsKICAgIGRmPC1nZXQocG9wc1tpXSkKICAgIHByb3AkbWFmX292ZXIwLjVfcHJvcFtpXTwtbnJvdyhkZltkZiRtYWY+MC41LF0pL25yb3coZGYpCn0KcHJvcDwtcmJpbmQocHJvcCwgYygiQ0ExNyIsIG5yb3coc2Fsb2NpW3NhbG9jaSRtYWY+MC41LF0pL25yb3coc2Fsb2NpKSkpCnByb3AkbWFmX292ZXIwLjVfcHJvcDwtYXMubnVtZXJpYyhwcm9wJG1hZl9vdmVyMC41X3Byb3ApCnByb3AKIyAgICBwb3AgbWFmX292ZXIwLjVfcHJvcAojMSBQV1MxNyAgICAgICAwLjAzMjc3NjU1CiMyICBTUzE3ICAgICAgIDAuMDM1NjEyOTgKIzMgIFRCMTcgICAgICAgMC4wMzA1NzA0NAojNCAgQkMxNyAgICAgICAwLjA0MDM0MDM3CiM1ICBXQTE3ICAgICAgIDAuMDM1OTI4MTQKIzYgIENBMTcgICAgICAgMC4xNDc0OTQ0OAoKCmdncGxvdChwcm9wLCBhZXMoeD1wb3AsIHk9bWFmX292ZXIwLjVfcHJvcCkpKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSt5bGFiKCJQcm9wb3J0aW9uIG9mIE1BRiA+IDAuNSBpbiBTYWxpbml0eSBBZGFwdGl2ZSBMb2NpIikKZ2dzYXZlKCIuLi9PdXRwdXQvU2FsaW5pdHkvUHJvcG9ydGlvbi5NQUYub3ZlcjAuNS5pbi5TYWxpbml0eS5BZGFwdGl2ZS5Mb2NpLnBuZyIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gNCwgZHBpPTMwMCkKYGBgCiFbXSguLi9PdXRwdXQvU2FsaW5pdHkvUHJvcG9ydGlvbi5NQUYub3ZlcjAuNS5pbi5TYWxpbml0eS5BZGFwdGl2ZS5Mb2NpLnBuZykKCiogQ0EgaGFzIGEgaGlnaGVyIHByb3BvcnRpb24gb2Ygc2FsaW5pdHkgYWRhcHRpdmUgbG9jaSB3aXRoIGFsbGVsZSBmcmVxLiA+MC41CiogSXMgdGhpcyBkdWUgdG8gaW52ZXJzaW9uIGluIGNocjEyPyAgCiogUmVtb3ZlIGxvY2kgd2l0aGluIENocjEyIGludmVyc2lvbgoKYGBge3IgZXZhbD1GQUxTRSwgd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFfQphZiRjb2xvcjwtIkEiCgojSXMgaXQgZHVlIHRvIGludmVyc2lvbj8KI3JlbW92ZSB0aGUgaW52ZXJzaW9uIHJlZ2lvbj8gKHJlbW92ZSBjaHIxMikKcHJvcDI8LWRhdGEuZnJhbWUocG9wPXBvcHMpCmZvciAoaSBpbiAxOmxlbmd0aChwb3BzKSl7CiAgICBkZjwtZ2V0KHBvcHNbaV0pCiAgICBkZjwtZGZbZGYkY2hyIT0iY2hyMTIiLF0KICAgIHByb3AyJG1hZl9vdmVyMC41X3Byb3BbaV08LW5yb3coZGZbZGYkbWFmPjAuNSxdKS9ucm93KGRmKQp9CnByb3AyPC1yYmluZChwcm9wMiwgYygiQ0ExNyIsIG5yb3coc2Fsb2NpW3NhbG9jaSRtYWY+MC41JnNhbG9jaSRjaHIhPSJjaHIxMiIsXSkvbnJvdyhzYWxvY2lbc2Fsb2NpJGNociE9ImNocjEyIixdKSkpCnByb3AyJG1hZl9vdmVyMC41X3Byb3A8LWFzLm51bWVyaWMocHJvcDIkbWFmX292ZXIwLjVfcHJvcCkKcHJvcDIKIyAgICBwb3AgbWFmX292ZXIwLjVfcHJvcAojMSBQV1MxNyAgICAgICAwLjAzNzg5MjI0CiMyICBTUzE3ICAgICAgIDAuMDQwMjYwNTEKIzMgIFRCMTcgICAgICAgMC4wMzkwNzYzOAojNCAgQkMxNyAgICAgICAwLjA0NDQwNDk3CiM1ICBXQTE3ICAgICAgIDAuMDM5MDc2MzgKIzYgIENBMTcgICAgICAgMC4wNDY3NzMyNAojdGhlIGRpZmZlcmVuY2UgZGlzYXBwZXJzIGJ5IHJlbW92aW5nIGNocjEyIChpbnZlcnNpb24pCgpnZ3Bsb3QocHJvcDIsIGFlcyh4PXBvcCwgeT1tYWZfb3ZlcjAuNV9wcm9wKSkrCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpK3lsYWIoIlByb3BvcnRpb24gb2YgTUFGID4gMC41IChubyBDaHIxMiBJbnYpIikKZ2dzYXZlKCIuLi9PdXRwdXQvU2FsaW5pdHkvUHJvcG9ydGlvbi5NQUYub3ZlcjAuNS5pbi5TYWxpbml0eS5BZGFwdGl2ZS5Mb2NpX3dpdGhvdXRDaHIxMkludi5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDQsIGRwaT0zMDApCgoKYGBgCgohW10oLi4vT3V0cHV0L1NhbGluaXR5L1Byb3BvcnRpb24uTUFGLm92ZXIwLjUuaW4uU2FsaW5pdHkuQWRhcHRpdmUuTG9jaV93aXRob3V0Q2hyMTJJbnYucG5nKSAgCgoKIyMjIGxvb2sgYXQgY2hyMSwgY2hyNCwgY2hyMTAsIGFuZCBjaHIxNiBzZXBhcmF0ZWx5CmBgYHtyIGV2YWw9RkFMU0UsIHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRX0KcG9wczI8LWMocG9wcywiQ0ExNyIpCkNBMTc8LXNhbG9jaQoKcHJvcDM8LWRhdGEuZnJhbWUocG9wPXBvcHMyKQpmb3IgKGkgaW4gMTpsZW5ndGgocG9wczIpKXsKICAgIGRmPC1nZXQocG9wczJbaV0pCiAgICBkZjE8LWRmW2RmJGNocj09ImNocjEiLF0KICAgIHByb3AzJGNocjFbaV08LW5yb3coZGYxW2RmMSRtYWY+MC41LF0pL25yb3coZGYxKQogICAgZGYxPC1kZltkZiRjaHI9PSJjaHI0IixdCiAgICBwcm9wMyRjaHI0W2ldPC1ucm93KGRmMVtkZjEkbWFmPjAuNSxdKS9ucm93KGRmMSkKICAgIGRmMTwtZGZbZGYkY2hyPT0iY2hyMTAiLF0KICAgIHByb3AzJGNocjEwW2ldPC1ucm93KGRmMVtkZjEkbWFmPjAuNSxdKS9ucm93KGRmMSkKICAgIGRmMTwtZGZbZGYkY2hyPT0iY2hyMTYiLF0KICAgIHByb3AzJGNocjE2W2ldPC1ucm93KGRmMVtkZjEkbWFmPjAuNSxdKS9ucm93KGRmMSkKfQoKcHJvcDNtPC1tZWx0KHByb3AzLCBpZC52YXJzPSJwb3AiKQpnZ3Bsb3QocHJvcDNtLCBhZXMoeD12YXJpYWJsZSwgeT12YWx1ZSwgY29sb3I9cG9wKSkrCiAgICBnZW9tX3BvaW50KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC41KSwgc2l6ZT0zKSsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoMS41LDIuNSwzLjUpLCBjb2xvcj0iZ3JheSIsc2l6ZT0wLjUpKwogICAgdGhlbWVfYncoKSt5bGFiKCJQcm9wb3J0aW9uIG9mIEFGID4wLjUiKSt4bGFiKCIiKSt0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpKwogICAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKQpnZ3NhdmUoIi4uL091dHB1dC9TYWxpbml0eS9Qcm9wQUZvdmVyMC41LmluLmFsbFBvcHMuY2g0LjEwLjE2LnBuZyIsIHdpZHRoPTcsIGhlaWdodD00LCBkcGk9MzAwICkgICAgCmBgYAohW10oLi4vT3V0cHV0L1NhbGluaXR5L1Byb3BBRm92ZXIwLjUuaW4uYWxsUG9wcy5jaDQuMTAuMTYucG5nKQoK